/**
 * <p>文件名:		xxx.java</p>
 * <p>版权:		CopyrightTag</p>
 * <p>公司:		CompanyTag</p>
 * @author		周华彬(zhouhuabin@chinatransinfo.com, zhou_hua_bin@163.com)
 */

package com.caits.lbs.framework.services;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.slf4j.Logger;
import org.springframework.util.Assert;

import com.caits.lbs.bean.dbmodel.ETBase;
import com.caits.lbs.framework.dao.BatchPersistenceDao;
import com.caits.lbs.framework.log.CommonSlf4jLogFactory;
import com.caits.lbs.framework.utils.CollectionUtils;

/**
 * <p>
 * BatchPersistenceService
 * </p>
 * <p>
 * 批量持久化服务，支持定时和大小提交
 * </p>
 * @author 周华彬(zhouhuabin@chinatransinfo.com, zhou_hua_bin@163.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">版本号</th>
 *          <th width="100px">动作</th>
 *          <th width="100px">修改人</th>
 *          <th width="100px">修改时间</th>
 *          </tr>
 *          <!-- 以 Table 方式书写修改历史 -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td>创建类</td>
 *          <td>zhouhuabin</td>
 *          <td>2015年12月8日 上午10:35:50</td>
 *          </tr>
 *          <tr>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          </tr>
 *          </table>
 */
public class BatchPersistenceService extends Thread implements Runnable {
	/** 变量:TODO,类型:Logger */
	protected  Logger LOG = CommonSlf4jLogFactory.getLog();
	
	/** 变量:待保存的数据列表,类型:List<ETBase> */
	private final List<ETBase> batchList = new LinkedList<ETBase>();
	/** 变量:批量提交大小,类型:int */
	private transient int batchSize = 20;
	/** 变量:间隔提交秒数,类型:int */
	private transient int batchInterval = 30;
	/** 为了支持大量的并发，特意加锁 */
	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private final Lock readLock = lock.readLock();//
	private final Lock writeLock = lock.writeLock();//

	/** 变量:持久化接口,类型:BatchPersistenceDao */
	private final BatchPersistenceDao batchDao;
	/** 变量:监视状态,类型:boolean */
	private boolean bWatch = false;

	/**
	 * 构造器
	 * @param batchSize 批量提交的大小
	 * @param interval 间隔的秒数
	 * @param batchDao
	 */
	public BatchPersistenceService(BatchPersistenceDao batchDao) {
		super();
		this.batchDao = batchDao;
	}
	/**
	 * 开始自动提交  void
	 */
	public synchronized void startWatch() {
		bWatch = true;
		start();
	}

	/**
	 * 停止自动提交  void
	 */
	public synchronized void stopWatch() {
		bWatch = false;
		try {
			notifyAll();
		} catch (Exception e) {
			LOG.info("通知本对象异常,msg=" + e.getLocalizedMessage(), e);
		}

	}

	/**
	 * 增加一个业务对象
	 * @param bizObj
	 * @return String
	 */
	public String addOneEntity(ETBase bizObj) {
		String ret = "0";
		try {
			Assert.notNull(bizObj, "存储对象不能为空");
			writeLock.lock();
			batchList.add(bizObj);
			writeLock.unlock();
			ret = "catchSize:" + batchList.size();
			if (batchList.size() >= batchSize) {
				ret = submitBatchEntity();
			}
		} catch (Exception e) {
			LOG.info("终端访问日志保存异常,msg=" + e.getLocalizedMessage(), e);
		}
		return ret;
	}

	/**
	 * 提交缓存的日志到数据库中
	 * @return String
	 */
	public String submitBatchEntity() {
		String ret = "0";
		try {
			Assert.notNull(batchList, "数据对象列表不能为空");
			ret = "catchSize:" + batchList.size();
			if (!CollectionUtils.isEmpty(batchList)) {
				int accessCount = 0;
				readLock.lock();
				accessCount = batchDao.persistenceList(batchList);
				readLock.unlock();
				writeLock.lock();
				batchList.clear();
				writeLock.unlock();
				LOG.info("批量提交数据成功,writenSize=" + accessCount);
				ret = "writenSize:" + accessCount;
			}
		} catch (Exception e) {
			LOG.info("批量保存数据异常,msg=" + e.getLocalizedMessage(), e);
		}
		return ret;
	}

	/* (non-Javadoc)
	 * @see java.lang.Runnable#run() */
	@Override
	public void run() {
		while (bWatch) {
			try {
				synchronized (this) {
					wait(batchInterval*1000);
				}
				submitBatchEntity();
			} catch (InterruptedException e) {
				LOG.error("线程被打断,需要重启启动startWatch,msg=" + e.getLocalizedMessage());
				break;
			}
		}
	}
	/**
	 * 获取属性 batchSize的值
	 * @return the batchSize : int
	 */
	public int getBatchSize() {
		return batchSize;
	}
	/**
	 * 设置属性batchSize的值，参数类型int
	 * @param batchSize the batchSize to set
	 */
	public void setBatchSize(int batchSize) {
		this.batchSize = batchSize;
	}
	/**
	 * 获取属性 batchInterval的值
	 * @return the batchInterval : int
	 */
	public int getBatchInterval() {
		return batchInterval;
	}
	/**
	 * 设置属性batchInterval的值，参数类型int
	 * @param batchInterval the batchInterval to set
	 */
	public void setBatchInterval(int batchInterval) {
		this.batchInterval = batchInterval;
	}
	
}
